/******************************************************************************
 *                     Organizacion de Datos - 75.06                          *
 *                         Cstedra Lic. Servetto                              *
 *            Facultad de Ingenieria - Universidad de Buenos Aires            *
 ******************************************************************************/ 

#include "ManejadorEspacioLibre.h"
#include <fstream>
#include <iostream>

#define CANTIDAD_DIGITOS 6
#define REGISTROS_POR_LINEA 16

namespace CapaFisica
{

	MapaExtension::MapaExtension(std::string clase, int tamanioBloque) : ManejadorEspacioLibre(clase)
	{
		
		this->tamanioBloque = tamanioBloque;
		Inicializar();

	}

	MapaExtension::~MapaExtension()
	{			
	}

	bool MapaExtension::EstaLibre(int grupoId)
	{
		// El bloque se encuentra libre si la extension es 0
		return elementos[grupoId] == 0;
	}

	bool MapaExtension::EstaInicializado(int grupoId)
	{
		// El bloque se encuentra inicializado si la extension no es -1.
		return elementos[grupoId] != -1;

	}

	void MapaExtension::Liberar(int grupoId)
	{
		
		// El bloque se encuentra libre si la extension es 0
		elementos[grupoId] = 0;

	}

	int MapaExtension::ObtenerTamanio(int grupoId)
	{

		// La extension es igual al tamanio del registro
		return this-> elementos[grupoId]; 
	
	}

	void MapaExtension::AsignarTamanio(int grupoId, int nuevoTamanio)
	{
		// La extension es igual al tamanio del registro
		this-> elementos[grupoId] = nuevoTamanio; 	
	}
	
	long MapaExtension::ObtenerTamanioArchivo()
	{

		long suma = 0;

		// Se calcula el tamanio total del archivo sumando todas las extensiones
		for ( int i=0 ; i < MAX_NUMBLOCKS ; i++)
		{
			// Si el elemento tiene extension negativa se llego al final del archivo
			if ( elementos[i] < 0)
				break;

			suma += elementos[i];
		}

		return suma;

	}

	int MapaExtension::ObtenerBloqueLibre(int tamanio)
	{
		
		for ( int i=0 ; i < MAX_NUMBLOCKS ; i++)
		{  
			// Si el elemento esta vacio (igual a cero) o no inicializado (negativo)
			// se coloca la extension definida por 'tamanio' y se devuelve el indice del registro
			if ( ( elementos[i] <= 0 ) )
			{
				elementos[i] = tamanio;
				return i;
			}
		}

		cerr << "CapaFisica->MapaExtension.cpp->MapaExtension::ObtenerBloqueLibre(int tamanio)" << endl << "Se ha alcanzado el numero de bloques maximos (" << MAX_NUMBLOCKS << ") permitidos." << endl;
		throw new exception();

	}
	
	void MapaExtension::Inicializar()
	{

		int tamanioLinea = ( CANTIDAD_DIGITOS + 1 )*REGISTROS_POR_LINEA + 1;
		
		char* buffer = new char[ tamanioLinea ];
		int contadorLinea = 0;

		// Se inicializan los elementos con una extension negativa
		for ( int i=0 ; i < MAX_NUMBLOCKS ; i++ )
			elementos[i]= -1;

		// Se lee linea por linea y se completan las extensiones
		while( file.getline( buffer, tamanioLinea ) )
		{
			for ( int i = 0 ; i < REGISTROS_POR_LINEA ; i++ )
			{
				int offset = i*(CANTIDAD_DIGITOS + 1);

				char primerDigito = buffer[ offset ];

				// Si el primer digito es 0 (fin de archivo) se termina el proceso
				if (primerDigito == 0)
					break;

				char espacioOcupado[CANTIDAD_DIGITOS];
				
				// Se leen los digitos del archivo
				for ( int j = offset ; j < offset + CANTIDAD_DIGITOS ; j++ )
					espacioOcupado[ j - offset ] = buffer[ j ];

				// Se convierte la cadena en un entero
				elementos[ contadorLinea*REGISTROS_POR_LINEA + i ] = StringAEntero( espacioOcupado );
			}

			contadorLinea++;
		}

	}

	void MapaExtension::GuardarArchivo()
	{
		
		// Se borran todos los flags
		file.clear();
		// Se posiciona el archivo al principio del archivo
		file.seekg(0,ios_base::beg);

		bool finEspacio = false;

		for ( int i = 0 ; i < ( MAX_NUMBLOCKS / REGISTROS_POR_LINEA ) ;  i++ )
		{
			if ( finEspacio ) 
				break;

			for ( int j=0 ; j < REGISTROS_POR_LINEA ; j++ )
			{	
				int offset = i*REGISTROS_POR_LINEA + j;

				if ( elementos[ offset ] == -1 )
				{
					finEspacio = true;
					break;
				}

				char* aux = EnteroAString( elementos[ offset ], CANTIDAD_DIGITOS );

				file << aux << ',';
			}
			file << endl;						
		}

	}

}
